package testCase.java.fastjson;

import java.sql.Date;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Map;
import java.util.Set;
import java.util.TreeSet;

import junit.framework.Assert;

import org.junit.Test;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.alibaba.fastjson.annotation.JSONCreator;
import com.alibaba.fastjson.annotation.JSONField;
import com.alibaba.fastjson.annotation.JSONType;
import com.alibaba.fastjson.parser.Feature;
import com.alibaba.fastjson.parser.ParserConfig;
import com.alibaba.fastjson.serializer.JSONSerializer;
import com.alibaba.fastjson.serializer.NameFilter;
import com.alibaba.fastjson.serializer.PropertyFilter;
import com.alibaba.fastjson.serializer.SerializeConfig;
import com.alibaba.fastjson.serializer.SerializeWriter;
import com.alibaba.fastjson.serializer.SerializerFeature;
import com.alibaba.fastjson.serializer.SimpleDateFormatSerializer;
import com.alibaba.fastjson.serializer.ValueFilter;

/**
 * 
 * @author lucky http://code.alibabatech.com/wiki/display/FastJSON/Tutorial
 */
public class sample1 {

	@Test
	public void testCURD() {
		String js = "{\"r\":[{\"id\":\"001\",\"db\":\"dbname\",\"ds\":\"tablename\",\"fld\":\"f1,f2,f3\",\"ps\":\"10\",\"p\":\"1\"},{\"fld1\":\"val1\",\"fld2\":\"val2\"},{\"fld3\":\"val3\",\"fld4\":\"val4\"},{\"f1\":\"v1\",\"f2\":\"v2\",\"f3\":\"v3\",\"f4\":\"v4\",\"fld5\":\"val5\"}],"
				+ "\"c\":[{\"fld1\":\"val1\",\"fld2\":\"val2\"}],"
				+ "\"u\":[{\"fld1\":\"val1\",\"fld2\":\"val2\",\"_w\":{\"f1\":\"v1\",\"f2\":\"v2\"}}],"
				+ "\"d\":[{\"fld1\":\"val1\"}]}";
		/**/
		js = "{\"args\":["+
			 "{\"k\":\"o\",\"v\":{\"id\":\"001\",\"db\":\"dbname\",\"ds\":\"tablename\",\"fld\":\"f1,f2,f3\",\"ps\":\"10\",\"p\":\"1\"}},"+
			 "{\"k\":\"r\",\"v\":[{\"fld1\":\"val1\",\"fld2\":\"val2\"},{\"fld3\":\"val3\",\"fld4\":\"val4\"},{\"f1\":\"v1\",\"f2\":\"v2\",\"f3\":\"v3\",\"f4\":\"v4\",\"fld5\":\"val5\"}]},"+			 
			 "{\"k\":\"c\",\"v\":[{\"fld1\":\"val1\",\"fld2\":\"val2\"}]},"+
			 "{\"k\":\"u\",\"v\":[{\"fld1\":\"val1\",\"fld2\":\"val2\"},{\"_w_f1\":\"v1\",\"_w_f2\":\"v2\"}]},"+
			 "{\"k\":\"d\",\"v\":[{\"fld1\":\"val1\"}]}"
			 + "]}";
			 
		StringBuilder sb_r = new StringBuilder();
		JSONObject json = JSON.parseObject(js);
		JSONArray json_tmp = null;
		
		JSONArray json_args = json.getJSONArray("args");
		
		for (int i = 0 ;i<json_args.size();i++){
			JSONObject json_arg = json_args.getJSONObject(i);
			String key = json_arg.getString("k");
			//curd & option
			switch (key) {
			case "o"://option
				JSONObject json_o = json_arg.getJSONObject("v");
				String dbName = json_o.getString("db");
				
				break;
			case "c"://create
				json_tmp = json_arg.getJSONArray("v");
				//{},{}
				for (int c = 0 ;c<json_tmp.size();c++){
					JSONObject item_c = json_tmp.getJSONObject(c);
					
					Set<String> keys_item =item_c.keySet();
					if (c>0){
						sb_r.append(") AND (");
					}else{
						sb_r.append("(");
					}

					int j =0;
					//{}
					for (String item : keys_item) {
						if(j>0){
							sb_r.append(" AND ");
						}
						sb_r.append(item).append(" = ").append(item_c.getString(item));
						j++;
					}
				}
				break;
			case "u"://update
				json_tmp = json_arg.getJSONArray("v");
				//{},{}
				for (int c = 0 ;c<json_tmp.size();c++){
					JSONObject item_c = json_tmp.getJSONObject(c);
					
					Set<String> keys_item =item_c.keySet();
					if (c>0){
						sb_r.append(") AND (");
					}else{
						sb_r.append("(");
					}

					int j =0;
					//{}
					for (String item : keys_item) {
						if(j>0){
							sb_r.append(" AND ");
						}
						sb_r.append(item).append(" = ").append(item_c.getString(item));
						j++;
					}
				}			
				break;
			case "r"://read
				json_tmp = json_arg.getJSONArray("v");
				//{},{}
				for (int c = 0 ;c<json_tmp.size();c++){
					JSONObject item_c = json_tmp.getJSONObject(c);
					
					Set<String> keys_item =item_c.keySet();
					if (c>0){
						sb_r.append(") AND (");
					}else{
						sb_r.append("(");
					}

					int j =0;
					//{}
					for (String item : keys_item) {
						if(j>0){
							sb_r.append(" AND ");
						}
						sb_r.append(item).append(" = ").append(item_c.getString(item));
						j++;
					}
				}
				break;
			case "d"://delete
				json_tmp = json_arg.getJSONArray("v");
				//{},{}
				for (int c = 0 ;c<json_tmp.size();c++){
					JSONObject item_c = json_tmp.getJSONObject(c);
					
					Set<String> keys_item =item_c.keySet();
					if (c>0){
						sb_r.append(") AND (");
					}else{
						sb_r.append("(");
					}

					int j =0;
					//{}
					for (String item : keys_item) {
						if(j>0){
							sb_r.append(" AND ");
						}
						sb_r.append(item).append(" = ").append(item_c.getString(item));
						j++;
					}
				}
				break;
			default:
				break;
			}
		}
		
		System.out.println(sb_r.toString());
	}
	@Test
	public void testToJSONObject() {

		String s = "{\"_d\":{\"user_gender\":\"1\",\"user_birth\":\"1974/1/1\",\"user_province\":\"\",\"user_city\":\"广州\",\"user_signature\":\"test\",\"user_notify\":\"1\"},\"_c\":{\"user_id\":\"e33037467dc54dcca777132f9cb045e2\"}}";
		JSONObject json = JSON.parseObject(s);
		System.out.println(json.getJSONObject("_d").getString("user_city"));
		System.out.println(json.getJSONObject("_c").getString("user_id"));
	}
	@Test
	public void testToString() {

		Group group = new Group();
		group.setId("0L");
		group.setName("admin");

		User guestUser = new User();
		guestUser.setFirstname("ray");
		guestUser.setLastname("huang");

		User rootUser = new User();
		rootUser.setFirstname("jack");
		rootUser.setLastname("lee");

		// group.getUsers().add(guestUser);
		// group.getUsers().add(rootUser);
		String jsonString = JSON.toJSONString(guestUser);

		System.out.println(jsonString);
	}

	@Test
	public void testToJSON() {
		// json_str =
		// "{"pom":{"cond":{},"ds":"pom","fields":"pom_id,vender_id","opt":{"size":"10","pages":"20"}}}";
		// String text =
		// "{\"firstname\":\"张老头's old man\", \"lastname\":\"chang\",\"age\":66}";
		// User user = JSON.parseObject(text, User.class);
		// System.out.println("parseObject>>" + user.getLastname());
		/*
		 * //主》》明细》》Size String text =
		 * "{\"pom\":{\"cond\":{\"pom_id\":\"0001\"},\"ds\":\"pom\",\"fields\":\"pom_id,vender_id\",\"opt\":{\"size\":\"10\",\"pages\":\"20\"}}"
		 * +
		 * ",\"pod\":{\"cond\":{\"pom_id\":\"0001\"},\"ds\":\"pod\",\"fields\":\"pod_id,mat_id\",\"opt\":{\"size\":\"10\",\"pages\":\"20\"}}"
		 * +
		 * ",\"posize\":{\"cond\":{\"pod_id\":\"1\"},\"ds\":\"posize\",\"fields\":\"posize_id,size_qty\",\"opt\":{\"size\":\"10\",\"pages\":\"20\"}}}"
		 * ; //主》》明细 String text =
		 * "{\"pom\":{\"cond\":{\"pom_id\":\"0001\"},\"ds\":\"pom\",\"fields\":\"pom_id,vender_id\",\"opt\":{\"size\":\"10\",\"pages\":\"20\"}}"
		 * +
		 * ",\"pod\":{\"cond\":{\"pom_id\":\"0001\"},\"ds\":\"pod\",\"fields\":\"pod_id,mat_id\",\"opt\":{\"size\":\"10\",\"pages\":\"20\"}}}"
		 * ;
		 */
		// 单一数据源
		String text = "{\"id\":\"pom\",\"cond\":{\"pom_id\":\"0001\"},\"ds\":\"v_pom\",\"fld\":\"pom_id,vender_id\",\"ps\":\"10\",\"count\":\"20\"}";

		JSONObject json = JSON.parseObject(text);

		// System.out.println("parseObject>>" +
		// json.getJSONObject("pom").getJSONObject("cond").getString("pom_id"));
		/*
		 * System.out.println("parseObject>>" +
		 * json.getJSONObject("pom").getJSONArray
		 * ("cond").getJSONObject(1).getString("pom_id")); for (int i =
		 * 0;i<json.getJSONObject("pom").getJSONArray("cond").size();i++){
		 * String val =
		 * json.getJSONObject("pom").getJSONArray("cond").getJSONObject
		 * (i).getString("pom_id"); System.out.println("parseObject>>" + val); }
		 */

		System.out.println("parseObject>> Size=" + String.valueOf(json.size()));
		text = "{\"id\":\"pom\",\"cond\":{\"pom_id\":\"0001\"},\"ds\":\"dax_ads\",\"fld\":\"pom_id,vender_id\",\"ps\":10,\"p\":1,\"count\":100}";
		json = JSON.parseObject(text);
		System.out.println("parseObject>> ds=" + json.getString("ds"));
		// json.

		getJSONValues(json);

	}

	private String getJSONValues(JSONObject o_json) {
		// 遍历JSONObject中的动态取值
		String ret = "";
		Set<String> keys = o_json.keySet();

		for (String key : keys) {
			if (!key.endsWith("cond")) {
				String className = o_json.getJSONObject(key).getClass()
						.getName();
				// o_json.
				// if(o_json.getJSONObject(key).getClass().getName().endsWith(""))
				System.out.println("className=" + className);
				if (className.endsWith("com.alibaba.fastjson.JSONObject")) {
					switch (key) {
					case "cond":
						break;
					case "ds":
						break;
					case "fields":
						break;
					case "opt":
						break;
					default:
						break;
					}
					//

				}
				if (className.endsWith("System.String")) {

					System.out.println(key + " = " + o_json.getString(key));
				}
			}

		}
		return ret;
	}

	@Test
	public void testNameFilter() {
		NameFilter filter = new NameFilter() {

			public String process(Object source, String name, Object value) {
				if (name.equals("id")) {
					return "ID";
				}

				return name;
			}

		};

		SerializeWriter out = new SerializeWriter();
		JSONSerializer serializer = new JSONSerializer(out);
		serializer.getNameFilters().add(filter);

		Map<String, Object> map = new HashMap<String, Object>();
		map.put("id", 0);
		serializer.write(map);

		String text = out.toString();
		Assert.assertEquals("{\"ID\":0}", text);
	}

	public static class Bean {
		private int id;
		private String name;

		public int getId() {
			return id;
		}

		public void setId(int id) {
			this.id = id;
		}

		public String getName() {
			return name;
		}

		public void setName(String name) {
			this.name = name;
		}

	}

	public static class A {
		private int id;
		private String name;

		public int getId() {
			return id;
		}

		public void setId(int id) {
			this.id = id;
		}

		public String getName() {
			return name;
		}

		public void setName(String name) {
			this.name = name;
		}
	}

	@Test
	public void testNameFilter2() {
		NameFilter filter = new NameFilter() {

			public String process(Object source, String name, Object value) {
				if (name.equals("id")) {
					return "ID";
				}

				return name;
			}

		};

		SerializeWriter out = new SerializeWriter();
		JSONSerializer serializer = new JSONSerializer(out);
		serializer.getNameFilters().add(filter);

		Bean a = new Bean();
		serializer.write(a);

		String text = out.toString();
		Assert.assertEquals("{\"ID\":0}", text);
	}

	@Test
	public void testPropertyFilter() {

		PropertyFilter filter = new PropertyFilter() {
			public boolean apply(Object source, String name, Object value) {
				return false;
			}
		};

		SerializeWriter out = new SerializeWriter();
		JSONSerializer serializer = new JSONSerializer(out);
		serializer.getPropertyFilters().add(filter);

		A a = new A();
		serializer.write(a);

		String text = out.toString();
		Assert.assertEquals("{}", text);
	}

	@Test
	public void testPropertyFilter2() {

		PropertyFilter filter = new PropertyFilter() {
			public boolean apply(Object source, String name, Object value) {
				if ("name".equals(name)) {
					return true;
				}
				return false;
			}
		};

		SerializeWriter out = new SerializeWriter();
		JSONSerializer serializer = new JSONSerializer(out);
		serializer.getPropertyFilters().add(filter);

		A a = new A();
		a.setName("chennp2008");
		serializer.write(a);

		String text = out.toString();
		Assert.assertEquals("{\"name\":\"chennp2008\"}", text);
	}

	/*
	 * public static class Bean2 { private int id; private String name; public
	 * Bean2(){ } public Bean2(int id, String name){ this.id = id; this.name =
	 * name; } public int getId() {return id;} public void setId(int id) {
	 * this.id = id;} public String getName() {return name;} public void
	 * setName(String name) {this.name = name;} }
	 * 
	 * /////////////////////
	 * 
	 * 
	 * @Test public void testTypeReference() { String text;
	 * 
	 * { List list = new ArrayList(); List mapList = new ArrayList();
	 * 
	 * Map<String, Bean2> map = new HashMap<String, Bean2>(); map.put("a", new
	 * Bean2(123, "马加爵")); map.put("b", new Bean2(234, "药家鑫")); map.put("c", new
	 * Bean2(456, "刘＋伟"));
	 * 
	 * mapList.add(map);
	 * 
	 * list.add(mapList);
	 * 
	 * text = JSON.toJSONString(list); }
	 * 
	 * System.out.println(text);
	 * 
	 * // text =
	 * [[{"b":{"name":"药家鑫","id":234},"c":{"name":"刘＋伟","id":456},"a":{
	 * "name":"马加爵","id":123}}]] List<List<Map<String, Bean2>>> list =
	 * JSON.parseObject(text, new TypeReference< List<List<Map<String, Bean2>>>
	 * >() {}); // 注意这里 Map<String, Bean2> map = list.get(0).get(0);
	 * 
	 * Assert.assertEquals(3, map.size());
	 * 
	 * Assert.assertEquals(123, ((Bean2) map.get("a")).getId());
	 * Assert.assertEquals(234, ((Bean2) map.get("b")).getId());
	 * Assert.assertEquals(456, ((Bean2) map.get("c")).getId());
	 * 
	 * Assert.assertEquals("马加爵", ((Bean2) map.get("a")).getName());
	 * Assert.assertEquals("药家鑫", ((Bean2) map.get("b")).getName());
	 * Assert.assertEquals("刘＋伟", ((Bean2) map.get("c")).getName());
	 * 
	 * }
	 */

	@Test
	public void testUseISO8601DateFormat() {

		// Decode
		SerializeWriter out = new SerializeWriter();

		JSONSerializer serializer = new JSONSerializer(out);
		serializer.config(SerializerFeature.UseISO8601DateFormat, true);
		Assert.assertEquals(true,
				serializer.isEnabled(SerializerFeature.UseISO8601DateFormat));
		serializer.write(new Date(1294552193254L));

		Assert.assertEquals("\"2011-01-09T13:49:53.254\"", out.toString());
		// Encode
		Date date = (Date) JSON.parseObject("\"2011-01-09T13:49:53\"",
				Date.class, Feature.AllowISO8601DateFormat);
		Assert.assertEquals(new Date(1294552193000L), date);
	}

	@Test
	public void testValueFilter() {

		ValueFilter filter = new ValueFilter() {

			public Object process(Object source, String name, Object value) {
				if (name.equals("name")) {
					return null;
				}

				return value;
			}

		};

		SerializeWriter out = new SerializeWriter();
		JSONSerializer serializer = new JSONSerializer(out);
		serializer.getValueFilters().add(filter);

		Map<String, Object> map = new HashMap<String, Object>();
		map.put("name", "AA");
		serializer.write(map);

		String text = out.toString();
		Assert.assertEquals("{}", text);

	}

	public class V1 {

		private int f2;
		private int f1;
		private int f4;
		private int f3;
		private int f5;

		public int getF2() {
			return f2;
		}

		public void setF2(int f2) {
			this.f2 = f2;
		}

		public int getF1() {
			return f1;
		}

		public void setF1(int f1) {
			this.f1 = f1;
		}

		public int getF4() {
			return f4;
		}

		public void setF4(int f4) {
			this.f4 = f4;
		}

		public int getF3() {
			return f3;
		}

		public void setF3(int f3) {
			this.f3 = f3;
		}

		public int getF5() {
			return f5;
		}

		public void setF5(int f5) {
			this.f5 = f5;
		}
	}

	@JSONType(orders = { "id", "name", "age" })
	public static class V2 {
		private int id;
		private String name;
		private int age;

		public int getId() {
			return id;
		}

		public void setId(int id) {
			this.id = id;
		}

		public String getName() {
			return name;
		}

		public void setName(String name) {
			this.name = name;
		}

		public int getAge() {
			return age;
		}

		public void setAge(int age) {
			this.age = age;
		}
	}

	@Test
	public void testSortField() throws Exception {
		V1 entity = new V1();
		V2 v2 = new V2();

		String text = JSON.toJSONString(entity, SerializerFeature.SortField);
		System.out.println("Sort>>>" + text);

		// 按字段顺序输出
		// {"f1":0,"f2":0,"f3":0,"f4":0,"f5":0}
		Assert.assertEquals("{\"f1\":0,\"f2\":0,\"f3\":0,\"f4\":0,\"f5\":0}",
				text);
		// text = "{\"f1\":0,\"f2\":0,\"f3\":0,\"f4\":0,\"f5\":0,\"f6\":1}";
		JSONObject object = JSON.parseObject(text);
		text = JSON.toJSONString(object, SerializerFeature.SortField);
		// System.out.println("Sort>>>" + object.getString("f6"));
		Assert.assertEquals("{\"f1\":0,\"f2\":0,\"f3\":0,\"f4\":0,\"f5\":0}",
				text);

		text = JSON.toJSONString(v2, SerializerFeature.SortField);
		System.out.println("Sort>>>" + text);
		Assert.assertEquals("{\"id\":0,\"age\":0}", text);

	}

	// 定制化mapping
	private static SerializeConfig mapping = new SerializeConfig();
	static {
		mapping.put(Date.class, new SimpleDateFormatSerializer("yyyy-MM-dd"));
	}

	@Test
	public void TestSimpleDataFormatSerializer() throws Exception {

		Date date = new Date(0);
		String text = JSON.toJSONString(date, mapping);
		// 在1.1.14之后的版本中，有更方便的定制化输出日期的方法。
		// text = JSON.toJSONStringWithDateFormat(date,
		// "yyyy-MM-dd HH:mm:ss.SSS");
		text = JSON.toJSONStringWithDateFormat(date, "yyyy-MM-dd");
		Assert.assertEquals(JSON
				.toJSONString(new SimpleDateFormat("yyyy-MM-dd").format(date)),
				text);

	}

	public static class Entity {
		private final int id;
		private final String name;

		@JSONCreator
		public Entity(@JSONField(name = "id") int id,
				@JSONField(name = "name") String name) {
			this.id = id;
			this.name = name;
		}

		public int getId() {
			return id;
		}

		public String getName() {
			return name;
		}
	}

	// 非缺省构造函数
	@Test
	public void testJSONCreator() throws Exception {
		Entity entity = new Entity(123, "菜姐");
		String text = JSON.toJSONString(entity);

		Entity entity2 = JSON.parseObject(text, Entity.class);
		Assert.assertEquals(entity.getId(), entity2.getId());
		Assert.assertEquals(entity.getName(), entity2.getName());
	}

	@Test
	public void testFactoryMethod() throws Exception {
		Entity entity = new Entity(123, "菜姐");
		String text = JSON.toJSONString(entity);

		Entity entity2 = JSON.parseObject(text, Entity.class);
		Assert.assertEquals(entity.getId(), entity2.getId());
		Assert.assertEquals(entity.getName(), entity2.getName());
	}

	public static class User2 {

		private int id;
		private String name;

		@JSONField(name = "uid")
		public int getId() {
			return id;
		}

		@JSONField(name = "uid")
		public void setId(int id) {
			this.id = id;
		}

		public String getName() {
			return name;
		}

		public void setName(String name) {
			this.name = name;
		}
	}

	// 別名
	@Test
	public void testAliases() throws Exception {
		User2 user = new User2();
		user.setId(123);
		user.setName("毛头");

		String text = JSON.toJSONString(user);
		Assert.assertEquals("{\"name\":\"毛头\",\"uid\":123}", text);
		System.out.println("別名>>>id字段被重定义为uid:" + text);
	}

	// loop
	@Test
	public void test_ref() throws Exception {
		Group1 admin = new Group1("admin");

		User1 jobs = new User1("jobs");
		User1 sager = new User1("sager");
		User1 sdh5724 = new User1("sdh5724");

		admin.getMembers().add(jobs);
		jobs.getGroup1s().add(admin);

		admin.getMembers().add(sager);
		sager.getGroup1s().add(admin);

		admin.getMembers().add(sdh5724);
		sdh5724.getGroup1s().add(admin);

		sager.setReportTo(sdh5724);
		jobs.setReportTo(sdh5724);

		SerializeConfig serializeConfig = new SerializeConfig();
		serializeConfig.setAsmEnable(false);
		String text = JSON.toJSONString(admin, serializeConfig,
				SerializerFeature.PrettyFormat);
		System.out.println("LOOP Invoke:" + text);

		ParserConfig config = new ParserConfig();
		config.setAsmEnable(false);

		JSON.parseObject(text, Group1.class, config, 0);
	}

	public static class Group1 {
		private String name;
		private ArrayList<User1> members = new ArrayList<User1>();

		public Group1() {
		}

		public Group1(String name) {
			this.name = name;
		}

		public String getName() {
			return name;
		}

		public void setName(String name) {
			this.name = name;
		}

		public ArrayList<User1> getMembers() {
			return members;
		}

		public void setMembers(ArrayList<User1> members) {
			this.members = members;
		}

		public String toString() {
			return this.name;
		}
	}

	public static class User1 {
		private String name;
		private ArrayList<Group1> groups = new ArrayList<Group1>();
		private User1 reportTo;

		public User1() {
		}

		public User1 getReportTo() {
			return reportTo;
		}

		public void setReportTo(User1 reportTo) {
			this.reportTo = reportTo;
		}

		public User1(String name) {
			this.name = name;
		}

		public String getName() {
			return name;
		}

		public void setName(String name) {
			this.name = name;
		}

		public ArrayList<Group1> getGroup1s() {
			return groups;
		}

		public void setGroup1s(ArrayList<Group1> groups) {
			this.groups = groups;
		}

		public String toString() {
			return this.name;
		}
	}

	@SuppressWarnings("deprecation")
	@Test
	public void testTab() throws Exception {

		// \t不转义时，IPhone上Objective-C的JSONKit库不能解析，为此Fastjson
		// 1.1.1之后的版本提供新特性：WriteTabAsSpecial。
		JSONObject json = new JSONObject();
		json.put("hello\t", "World\t!");
		// Assert.assertEquals("{\"hello\t\":\"World\t!\"}",
		// JSON.toJSONString(json));
		System.out.println("对Tab进行转义>>>" + JSON.toJSON(json));
		Assert.assertEquals("{\"hello\\t\":\"World\\t!\"}",
				JSON.toJSONString(json, SerializerFeature.WriteTabAsSpecial));
		Assert.assertEquals("{'hello\\t':'World\\t!'}", JSON.toJSONString(json,
				SerializerFeature.WriteTabAsSpecial,
				SerializerFeature.UseSingleQuotes));

	}
}
